﻿using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using SilverAmp.Common;
using SilverAmp.Common.DecoupledEvents;
using SilverAmp.Views;

namespace SilverAmp
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public ICommand PlayCommand { get; private set; }
        public ICommand StopCommand { get; private set; }
        public ICommand NextCommand { get; private set; }
        public ICommand PreviousCommand { get; private set; }
        public ICommand ShowMenu { get; private set; }

        [Export]
        public MainModel Model { get; set; }

        public ITrackInfo CurrentlyPlayingSong
        {
            get { return Model.CurrentlyPlayingSong; }
            set
            {
                if (Model.CurrentlyPlayingSong != value)
                {
                    Model.CurrentlyPlayingSong = value;
                    NotifyPropertyChanged("CurrentlyPlayingSong");
                }
            }
        }

        public ITrackInfo SelectedSong
        {
            get { return Model.SelectedSong; }
            set
            {
                Model.SelectedSong = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("SelectedSong"));
            }
        }

        private bool _isPlaying;
        public bool IsPlaying
        {
            get { return _isPlaying; }
            set
            {
                _isPlaying = value;

                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("IsPlaying"));
            }
        }
        public string CurrentTime
        {
            get
            {
                return string.Format("{0:00}:{1:00}", _musicPlayer.Position.Minutes,
                                        _musicPlayer.Position.Seconds);
            }
        }
        public string TotalTime
        {
            get
            {
                return string.Format("{0:00}:{1:00}", _musicPlayer.NaturalDuration.TimeSpan.Minutes,
                                        _musicPlayer.NaturalDuration.TimeSpan.Seconds);
            }
        }
        public long CurrentPosition
        {
            get
            {
                return (long)_musicPlayer.Position.TotalMilliseconds;
            }
        }
        public long TotalPosition
        {
            get
            {
                return (long)_musicPlayer.NaturalDuration.TimeSpan.TotalMilliseconds;
            }
        }

        private readonly MediaElement _musicPlayer;
        private readonly DispatcherTimer _timer;

        private DecoupledEventAggregator eventAggregator;
        public MainViewModel()
        {

            Model = new MainModel();
            _musicPlayer = new MediaElement();
            InitializeCommands();
            _timer = InitializePositionSliderUpdates();
            eventAggregator = DecoupledEventAggregator.GetInstance();
            eventAggregator.GetEvent<SelectSongEvent>().Subscribe(OnSelectSongEvent);
            eventAggregator.GetEvent<FileDroppedEvent>().Subscribe(OnFileDroppedEvent);
            eventAggregator.GetEvent<StartPlayingEvent>().Subscribe(OnStartPlaying);
            SetupNotificationWindow();
        }

        private void SetupNotificationWindow()
        {
            notify = new NotificationWindow();
            notify.Width = 330;
            notify.Height = 75;
           
        }

        private NotificationWindow notify;
        private void OnStartPlaying(ITrackInfo trackInfo)
        {
            notify.Close();
            //TextBlock tb = new TextBlock();
            //tb.Text = "Playing:" + trackInfo.Name;
            //tb.FontSize = 24;
            
            //notify.Content = tb;
            notify.Content = new NotificationView()
                                 {
                                     DataContext = SelectedSong
                                 };
            notify.Show(3000);
        }

        private void OnFileDroppedEvent(IDataObject droppedData)
        {
            if (!droppedData.GetDataPresent(DataFormats.FileDrop)) return;

            var files = droppedData.GetData(DataFormats.FileDrop) as FileInfo[];

            if (files != null && files[0].Extension.ToLower()==".mp3")
            {
                
                if(!Model.FileInPlaylist(files[0]))
                {
                    Model.AddFileToPlaylist(files[0]);
                }
                SelectedSong = Model.SelectSong(files[0]);
                PlayCommand.Execute(string.Empty);
            }
         
        }

        private void OnSelectSongEvent(ITrackInfo trackInfo)
        {
            SelectedSong = trackInfo;
        }

        /// <summary>
        /// Initializes the timer for updating the track position slider.
        /// </summary>
        /// <returns>an initialized DispatcherTimer</returns>
        private DispatcherTimer InitializePositionSliderUpdates()
        {
            var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
            timer.Tick += delegate
                               {
                                   NotifyPropertyChanged("CurrentTime");
                                   NotifyPropertyChanged("TotalTime");
                                   NotifyPropertyChanged("CurrentPosition");
                                   NotifyPropertyChanged("TotalPosition");
                               };
            return timer;
        }

        private void InitializeCommands()
        {
            PlayCommand = new DelegateCommand<string>(OnPlayCommand);
            StopCommand = new DelegateCommand<string>(OnStopCommand);

            PreviousCommand = new DelegateCommand<string>(OnPreviousCommand);
            NextCommand = new DelegateCommand<string>(OnNextCommand);
            ShowMenu = new DelegateCommand<string>(OnShowMenuCommand);
        }

        private void OnShowMenuCommand(string obj)
        {
            DecoupledEventAggregator.GetInstance().GetEvent<ShowMenuEvent>().Publish(string.Empty);
        }

        private void OnNextCommand(string obj)
        {

        }

        private void OnPreviousCommand(string obj)
        {

        }

        private void OnStopCommand(string obj)
        {
            _musicPlayer.Pause();
            _timer.Stop();
            IsPlaying = false;
        }

        private void OnPlayCommand(string obj)
        {
            if (SelectedSong != null)
            {

                if (_musicPlayer.CurrentState == MediaElementState.Stopped ||
                    _musicPlayer.CurrentState == MediaElementState.Closed ||
                    (_musicPlayer.CurrentState == MediaElementState.Playing &&
                      CurrentlyPlayingSong != SelectedSong))
                {
                    CurrentlyPlayingSong = SelectedSong;
                    MediaFile f = CurrentlyPlayingSong.Fileinfo;

                    _musicPlayer.SetSource(f.ReadStream);
                    _musicPlayer.Play();

                    DecoupledEventAggregator.GetInstance().GetEvent<StartPlayingEvent>().Publish(SelectedSong);

                    _timer.Start();
                    IsPlaying = true;
                }
                else
                {
                    if (_musicPlayer.CurrentState == MediaElementState.Paused)
                    {
                        _musicPlayer.Play();
                        _timer.Start();
                        IsPlaying = true;
                    }

                }
            }
        }

        public void LoadSongInformation()
        {
            Model.LoadID3SongInformation();
        }


        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}